home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swagg_m.zip / MISC.SWG / 0112_Patch TP's Runtime Library.pas < prev    next >
Pascal/Delphi Source File  |  1995-03-03  |  6KB  |  156 lines

  1. {
  2. George Kalemanis <usr5086a@tso.uc.edu>
  3. PATCH.PAS - Patching Turbo's Runtime Library On The Fly
  4. }
  5.  
  6. Unit patch;
  7.  
  8. Interface
  9.  
  10. {$R-,S-,I- }
  11.  
  12. Function CPUOk : Boolean;
  13.  
  14. InLine(
  15.            { Sort out 8086/8088 from 80286/i386/i486 }
  16.   $31/$C0/               {      XOR   AX, AX     }
  17.   $50/                   {      PUSH  AX         }
  18.   $9D/                   {      POPF             }
  19.   $9C/                   {      PUSHF            }
  20.   $58/                   {      POP   AX         }
  21.            { If the flag register holds $F000, then it is a 8086/8088 }
  22.   $25/$00/$F0/           {      AND   AX, $F000  }
  23.   $3D/$00/$F0/           {      CMP   AX, $F000  }
  24.   $74/$10/               {      JE    @@1        }
  25.            { Sort out 80286 from 80386/80486 }
  26.   $B8/$00/$F0/           {      MOV   AX, $F000  }
  27.   $50/                   {      PUSH  AX         }
  28.   $9D/                   {      POPF             }
  29.   $9C/                   {      PUSHF            }
  30.   $58/                   {      POP   AX         }
  31.            { If the flag register <> 2, then it is a 80286 }
  32.   $25/$00/$F0/           {      AND   AX, $F000  }
  33.   $74/$04/               {      JZ    @@1        }
  34.   $B0/$01/               {      MOV   AL, True   }
  35.   $EB/$02/               {      JMP   Short @@2  }
  36.   $B0/$00);              { @@1: MOV   AL, False  }
  37.                          { @@2: }
  38. Implementation
  39.  
  40. Const
  41.   dummy        : LongInt = 1;
  42.  
  43. Type
  44.   SystemProc   = Procedure;
  45.   SystemCall   = ^SystemProc;      { Pointer to the caller's address }
  46.  
  47. Var
  48.   CallAddr     : ^SystemCall;      { Pointer to the procedure to be patched }
  49.  
  50. { Copy instruction pointer of caller from the stack }
  51.  
  52. Function IPtr : Word;
  53.  
  54. InLine(
  55.   $8B/$46/$02);          {      MOV   AX, [BP+2] }
  56.  
  57. { This patch speeds up 4-byte signed integer division by 600% }
  58.  
  59. Procedure DivisionPatch;
  60.  
  61. Const
  62.   PatchCode    : Array[0..21] of Byte = (
  63.            { Push dividend on the stack, pop it in a 32-bits register
  64.              To avoid division by zero errors, extend it to a quadword }
  65.                    $52,            {  PUSH  DX        }
  66.                    $50,            {  PUSH  AX        }
  67.                    $66, $58,       {  POP   EAX       }
  68.                    $66, $99,       {  CDQ             }
  69.            { Push divisor on the stack, pop it in a 32-bit register.
  70.              Perform the division }
  71.                    $53,            {  PUSH  BX        }
  72.                    $51,            {  PUSH  CX        }
  73.                    $66, $5E,       {  POP   ESI       }
  74.                    $66, $F7, $FE,  {  IDIV  ESI       }
  75.            { Push remainder on the stack, pop it in 16-bits registers }
  76.                    $66, $52,       {  PUSH  EDX       }
  77.                    $59,            {  POP   CX        }
  78.                    $5B,            {  POP   BX        }
  79.            { Push quotient on the stack, pop it in 16-bits registers }
  80.                    $66, $50,       {  PUSH  EAX       }
  81.                    $58,            {  POP   AX        }
  82.                    $5A,            {  POP   DX        }
  83.                    $CB);           {  RETF            }
  84. Begin
  85.   CallAddr := Ptr(CSeg, IPtr-14);
  86.   Move(PatchCode, CallAddr^^, SizeOf(PatchCode));
  87. end;  { LongIntDivisionPatch }
  88.  
  89. { Provided the product > 2^16, this patch speeds up 4-byte signed integer
  90.    multiplication by 5%  }
  91.  
  92. Procedure MultiplyPatch;
  93.  
  94. Const
  95.   PatchCode    : Array[0..15] of Byte = (
  96.            { Push first operand on the stack, pop it in a 32-bits register }
  97.                    $52,            {  PUSH  DX        }
  98.                    $50,            {  PUSH  AX        }
  99.                    $66, $58,       {  POP   EAX       }
  100.            { Push second operand on the stack, pop it in a 32-bits register
  101.              Perform the multiplication }
  102.                    $53,            {  PUSH  BX        }
  103.                    $51,            {  PUSH  CX        }
  104.                    $66, $5A,       {  POP   EDX       }
  105.                    $66, $F7, $EA,  {  IMUL  EDX       }
  106.            { Push product on the stack, pop it in 16-bits registers }
  107.                    $66, $50,       {  PUSH  EAX       }
  108.                    $58,            {  POP   AX        }
  109.                    $5A,            {  POP   DX        }
  110.                    $CB);           {  RETF            }
  111. Begin
  112.   CallAddr := Ptr(CSeg, IPtr-14);
  113.   Move(PatchCode, CallAddr^^, SizeOf(PatchCode));
  114. end;  { MultiplyPatch }
  115.  
  116. { Shift directly across multiple words, rather than in a loop }
  117.  
  118. Procedure ShiftLeftPatch;
  119.  
  120. Const
  121.   PatchCode    : Array[0..3] of Byte = (
  122.                    $0F, $A5, $C2,  {  SHLD DX, AX, CL }
  123.                    $CB);           {  RETF            }
  124. Begin
  125.   CallAddr := Ptr(CSeg, IPtr-14);
  126.   Move(PatchCode, CallAddr^^, SizeOf(PatchCode));
  127. end;  { ShiftLeftPatch }
  128.  
  129. { Shift directly across multiple words, rather than in a loop }
  130.  
  131. Procedure ShiftRightPatch;
  132.  
  133. Const
  134.   PatchCode    : Array[0..3] of Byte = (
  135.                    $0F, $AD, $C2,  {  SHRD DX, AX, CL }
  136.                    $CB);           {  RETF            }
  137. Begin
  138.   CallAddr := Ptr(CSeg, IPtr-14);
  139.   Move(PatchCode, CallAddr^^, SizeOf(PatchCode));
  140. end;  { ShiftRightPatch }
  141.  
  142. Begin  { Patch }
  143.   If CPUOk Then                        { It's a 32-bitter }
  144.     Begin
  145.       dummy := dummy div dummy;
  146.       DivisionPatch;
  147.       dummy := dummy*dummy;
  148.       MultiplyPatch;
  149.       dummy := dummy shl 1;
  150.       ShiftLeftPatch;
  151.       dummy := dummy shr 1;
  152.       ShiftRightPatch;
  153.     end;
  154. end.  { Patch }
  155.  
  156.